from flask import Flask, render_template, jsonify, Response
from flask_socketio import SocketIO, emit
import json
import socket
import threading
import time
import requests
import logging
from datetime import datetime

# 配置日志
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

app = Flask(__name__)
app.config['SECRET_KEY'] = 'rk3588_video_test'
socketio = SocketIO(app, cors_allowed_origins="*", logger=False)

# 全局状态
video_data = {
    'connected': False,
    'protocol': 'Unknown',
    'status': 'offline',
    'codec': 'Unknown',
    'resolution': 'Unknown',
    'fps': 0,
    'bitrate': 'Unknown',
    'latency': 'Unknown',
    'last_update': None
}

# TCP服务器状态
tcp_server_running = False
tcp_server_initialized = False

def start_tcp_data_server():
    """启动TCP数据接收服务器"""
    global tcp_server_running, tcp_server_initialized
    
    if tcp_server_running or tcp_server_initialized:
        return
    
    tcp_server_initialized = True
        
    def tcp_server_thread():
        global tcp_server_running
        
        server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        
        try:
            server_socket.bind(('0.0.0.0', 9000))
            server_socket.listen(5)
            tcp_server_running = True
            print("[成功] TCP数据服务器启动成功: 0.0.0.0:9000")
            
            while tcp_server_running:
                try:
                    client_socket, addr = server_socket.accept()
                    print(f"[连接] RK3588设备连接: {addr}")
                    
                    def handle_client():
                        video_data['connected'] = True
                        socketio.emit('connection_update', {'connected': True})
                        
                        try:
                            buffer = ""
                            while tcp_server_running:
                                data = client_socket.recv(4096)
                                if not data:
                                    break
                                
                                buffer += data.decode('utf-8')
                                
                                # 处理JSON消息
                                while '\n' in buffer:
                                    line, buffer = buffer.split('\n', 1)
                                    if line.strip():
                                        try:
                                            msg = json.loads(line.strip())
                                            
                                            if msg.get('type') == 'video':
                                                data_payload = msg.get('data', {})
                                                video_data.update(data_payload)
                                                video_data['last_update'] = datetime.now().strftime('%H:%M:%S')
                                                
                                                print(f"[视频] 数据更新: {data_payload.get('protocol', 'Unknown')} - {data_payload.get('codec', 'Unknown')}")
                                                socketio.emit('video_update', video_data)
                                                
                                            elif msg.get('type') == 'heartbeat':
                                                print("[心跳] 收到心跳包")
                                                
                                        except json.JSONDecodeError:
                                            logger.warning(f"JSON解析失败: {line[:100]}")
                                        except Exception as e:
                                            logger.error(f"消息处理错误: {e}")
                                            
                        except Exception as e:
                            logger.error(f"客户端处理错误: {e}")
                        finally:
                            video_data['connected'] = False
                            video_data['status'] = 'offline'
                            client_socket.close()
                            socketio.emit('connection_update', {'connected': False})
                            print(f"[断开] RK3588设备断开: {addr}")
                    
                    # 为每个客户端创建处理线程
                    client_thread = threading.Thread(target=handle_client, daemon=True)
                    client_thread.start()
                    
                except Exception as e:
                    if tcp_server_running:
                        logger.error(f"接受连接失败: {e}")
                        
        except Exception as e:
            logger.error(f"TCP服务器启动失败: {e}")
        finally:
            tcp_server_running = False
            if server_socket:
                server_socket.close()
    
    # 在后台线程中启动TCP服务器
    tcp_thread = threading.Thread(target=tcp_server_thread, daemon=True)
    tcp_thread.start()
    
    # 等待服务器启动
    time.sleep(0.5)

# Flask应用初始化 - 兼容新版本Flask
@app.before_request
def initialize_app():
    """Flask应用初始化 - 只执行一次"""
    global tcp_server_initialized
    if not tcp_server_initialized:
        print("[启动] 初始化RK3588视频流测试系统...")
        start_tcp_data_server()

@app.route('/')
def index():
    """主页"""
    return render_template('index.html')

@app.route('/api/status')
def api_status():
    """获取系统状态API"""
    return jsonify({
        'video_data': video_data,
        'tcp_server_running': tcp_server_running,
        'server_time': datetime.now().isoformat()
    })

@app.route('/video_proxy')
def video_proxy():
    """增强的MJPEG视频流代理 - 支持TCP直连和HTTP"""
    def generate_video():
        max_retries = 3
        retry_count = 0
        
        while retry_count < max_retries:
            try:
                logger.info(f"[视频] 尝试连接MJPEG流 (第{retry_count + 1}次)")
                
                # 方法1: 尝试HTTP连接
                try:
                    response = requests.get(
                        'http://192.168.233.110:8080',
                        stream=True,
                        timeout=5,
                        headers={
                            'Connection': 'keep-alive',
                            'User-Agent': 'RK3588-Video-Proxy'
                        }
                    )
                    
                    if response.status_code == 200:
                        logger.info("[视频] MJPEG视频流连接成功 (HTTP)")
                        
                        for chunk in response.iter_content(chunk_size=8192):
                            if chunk:
                                yield chunk
                        break
                    else:
                        logger.warning(f"[视频] HTTP状态码错误: {response.status_code}")
                        raise Exception("HTTP连接失败")
                        
                except (requests.exceptions.ConnectionError, requests.exceptions.Timeout, Exception):
                    logger.info("[视频] HTTP连接失败，尝试TCP直连...")
                    
                    # 方法2: 基础TCP直连 - 简单可靠
                    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                    sock.settimeout(15)
                    sock.connect(('192.168.233.110', 8080))
                    
                    logger.info("[视频] MJPEG视频流连接成功 (TCP)")
                    
                    # 简单数据转发
                    while True:
                        data = sock.recv(8192)
                        if not data:
                            break
                        yield data
                    
                    sock.close()
                    break
                    
            except socket.timeout:
                logger.warning(f"[视频] TCP连接超时 (尝试 {retry_count + 1}/{max_retries})")
                retry_count += 1
                if retry_count < max_retries:
                    time.sleep(2)
                
            except socket.error as e:
                logger.warning(f"[视频] TCP连接失败: {str(e)} (尝试 {retry_count + 1}/{max_retries})")
                retry_count += 1
                if retry_count < max_retries:
                    time.sleep(2)
                
            except Exception as e:
                logger.error(f"[视频] 视频代理错误: {e}")
                retry_count += 1
                if retry_count < max_retries:
                    time.sleep(2)
        
        # 所有重试失败后，返回错误信息
        logger.error("[视频] 所有连接方法失败，返回错误页面")
        error_response = f"""
        <div style="font-family: Arial; padding: 20px; background: #f8f9fa; text-align: center;">
            <h3 style="color: #dc3545;">视频流暂时不可用</h3>
            <p><strong>状态:</strong> TCP和HTTP连接均失败</p>
            <p><strong>目标:</strong> 192.168.233.110:8080</p>
            <p><strong>时间:</strong> {datetime.now().strftime('%H:%M:%S')}</p>
            <p style="color: #6c757d; margin-top: 15px;">请检查RK3588设备状态</p>
        </div>
        """.encode('utf-8')
        yield b'--frame\r\nContent-Type: text/html; charset=utf-8\r\n\r\n' + error_response + b'\r\n'
    
    return Response(
        generate_video(),
        mimetype='multipart/x-mixed-replace; boundary=frame',
        headers={
            'Cache-Control': 'no-cache, no-store, must-revalidate',
            'Pragma': 'no-cache',
            'Expires': '0',
            'Access-Control-Allow-Origin': '*'
        }
    )

# WebSocket事件处理
@socketio.on('connect')
def handle_connect():
    """WebSocket客户端连接"""
    logger.info("Web客户端连接")
    emit('video_update', video_data)
    emit('connection_update', {'connected': video_data['connected']})

@socketio.on('request_status')
def handle_request_status():
    """请求状态更新"""
    emit('video_update', video_data)
    emit('connection_update', {'connected': video_data['connected']})

@socketio.on('disconnect')
def handle_disconnect():
    """WebSocket客户端断开"""
    logger.info("Web客户端断开")

# 无论如何都确保监听所有接口
import os
if os.environ.get('FLASK_RUN_HOST') is None:
    os.environ['FLASK_RUN_HOST'] = '0.0.0.0'
if os.environ.get('FLASK_RUN_PORT') is None:
    os.environ['FLASK_RUN_PORT'] = '5000'

# 如果直接运行python app.py时的配置
if __name__ == '__main__':
    print("[直接运行] 启动模式")
    start_tcp_data_server()
    print("[Web] 界面地址: http://192.168.233.187:5000")
    socketio.run(app, debug=False, host='0.0.0.0', port=5000)
